/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package ec.edu.ucuenca.pagina_asos.controller;

import ec.edu.ucuenca.pagina_asos.controller.exceptions.NonexistentEntityException;
import ec.edu.ucuenca.pagina_asos.controller.exceptions.PreexistingEntityException;
import ec.edu.ucuenca.pagina_asos.controller.exceptions.RollbackFailureException;
import java.io.Serializable;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.transaction.UserTransaction;

/**
 *
 * @author Johnny
 */
public class GenericJpaController<T> implements Serializable {
    private T objeto;

    public T getObjeto() {
        return objeto;
    }

    public void setObjeto(T objeto) {
        this.objeto = objeto;
    }
    
    public GenericJpaController(UserTransaction utx, EntityManagerFactory emf) {
        this.utx = utx;
        this.emf = emf;
    }
    private UserTransaction utx = null;
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }
    
    public void create(T clase) throws  PreexistingEntityException, RollbackFailureException, Exception {
        EntityManager em = null;
        try {
            utx.begin();
            em = getEntityManager();
            
            //em.getTransaction().begin();
            em.persist(clase);
            //em.getTransaction().commit();
            utx.commit();
        } catch (Exception ex) {
            if(ex.getCause().toString().contains("ConstraintViolationException"))
                {
                    
                }
            try {
                
                //utx.rollback();
            } catch (Exception re) {
               
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void edit(T clase) throws NonexistentEntityException, RollbackFailureException, Exception {
        EntityManager em = null;
        try {
            utx.begin();
            em = getEntityManager();
            clase = em.merge(clase);
            utx.commit();
        } catch (Exception ex) {
            try {
                utx.rollback();
            } catch (Exception re) {
                throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
            }
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(T obj,Object id) throws NonexistentEntityException, RollbackFailureException, Exception {
        EntityManager em = null;
        try {
            utx.begin();
            em = getEntityManager();
            T clase=null;
            try {
                clase = (T)em.getReference(obj.getClass(), id);
                
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The clase with id " + id + " no longer exists.", enfe);
            }
            em.remove(clase);
            utx.commit();
        } catch (Exception ex) {
            try {
                utx.rollback();
                System.out.println(ex.getLocalizedMessage());
            } catch (Exception re) {
                throw new RollbackFailureException("An error occurred attempting to roll back the transaction.", re);
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<T> findEntities(T obj) {
        return findEntities(true, -1, -1,obj);
    }

    public List<T> findEntities(int maxResults, int firstResult, T obj) {
        return findEntities(false, maxResults, firstResult,obj);
    }

    private List<T> findEntities(boolean all, int maxResults, int firstResult, T obj) {
        EntityManager em = getEntityManager();
        try {
            
            
            String clase = obj.getClass().getSimpleName();
            Query q = em.createQuery("select object(o) from "+clase+" as o");
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }
    public List<T> findEntities(T obj, String where) {
        EntityManager em = getEntityManager();
        try {
            
            
            String clase = obj.getClass().getSimpleName();
            Query q = em.createQuery("select object(o) from "+clase+" as o where "+ where);
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public T find(T obj,Object id) {
        EntityManager em = getEntityManager();
        try {
            return (T)em.find(obj.getClass(), id);
        } finally {
            em.close();
        }
    }
    public T findInt(T obj,Integer id) {
        EntityManager em = getEntityManager();
        try {
            return (T)em.find(obj.getClass(), id);
        } finally {
            em.close();
        }
    }

    public int getCount(T obj) {
        EntityManager em = getEntityManager();
        try {
            String clase = obj.getClass().getSimpleName();
            Query q = em.createQuery("select count(o) from "+clase+" as o");
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }
    
}
